package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.heima.article.dto.ArticleDto;
import com.heima.article.dto.ArticleHomeDto;
import com.heima.article.dto.ArticleInfoDto;
import com.heima.article.entity.ApArticle;
import com.heima.article.entity.ApArticleContent;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.IApArticleContentService;
import com.heima.article.service.IApArticleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.task.ArticleHtmlTasks;
import com.heima.common.dto.ResponseResult;
import com.heima.common.enums.AppHttpCodeEnum;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 * 文章信息表，存储已发布的文章 服务实现类
 * </p>
 *
 * @author syl
 * @since 2022-06-30
 */
@Service
public class ApArticleServiceImpl extends ServiceImpl<ApArticleMapper, ApArticle> implements IApArticleService {

    @Autowired
    private IApArticleContentService iApArticleContentService;

    @Autowired
    private ArticleHtmlTasks articleHtmlTasks;

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Override
    public ResponseResult<Long> saveArticle(ArticleDto dto) {
        if(dto.getId() !=null){
            //修改操作
            ApArticle apArticle = new ApArticle();
            BeanUtils.copyProperties(dto,apArticle);
            this.updateById(apArticle);
            LambdaQueryWrapper<ApArticleContent> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ApArticleContent::getArticleId,apArticle.getId());
            queryWrapper.eq(ApArticleContent::getContent,dto.getContent());
            iApArticleContentService.update(queryWrapper);
            return ResponseResult.okResult(apArticle.getId());
        }else {
            //新增操作
            ApArticle apArticle = new ApArticle();
            BeanUtils.copyProperties(dto,apArticle);
            apArticle.setCreatedTime(new Date());
            apArticle.setId(null);
            this.save(apArticle);
            ApArticleContent apArticleContent = new ApArticleContent();
            apArticleContent.setId(null);
            apArticleContent.setArticleId(apArticle.getId());
            apArticleContent.setContent(dto.getContent());
            iApArticleContentService.save(apArticleContent);
            articleHtmlTasks.createHtml(apArticle,dto.getContent());
            return ResponseResult.okResult(apArticle.getId());
        }
    }

    @Override
    public ResponseResult load(ArticleHomeDto dto, int type) {
        //判断是否是首页加载数据,如果是首页的话,先从redis中查询数据
        if(dto.getLoaddir()==1){
            //从redis中查询数据,按照分值从大到小排列
            String key = "hot_article_first_page_" + dto.getChannelId();
            long strat = 0;
            long end = dto.getSize()-1;
            Set<String> strings = redisTemplate.boundZSetOps(key).reverseRange(strat, end);
            List<ApArticle> apArticles = new ArrayList<>();
            for (String string : strings) {
                ApArticle apArticle = JSON.parseObject(string, ApArticle.class);
                apArticles.add(apArticle);
            }
            if (apArticles.size()>=dto.getSize()){
                return ResponseResult.okResult(apArticles);
            }
        }
        LambdaQueryWrapper<ApArticle> queryWrapper = new LambdaQueryWrapper<>();
        //根据频道id查询
        if (dto.getChannelId()!=null&&dto.getChannelId()!=0){
            queryWrapper.eq(ApArticle::getChannelId,dto.getChannelId());
        }
        if(type==0){
            queryWrapper.gt(ApArticle::getPublishTime,dto.getMaxTime());
        }
        if(type==1){
          queryWrapper.lt(ApArticle::getPublishTime,dto.getMinTime());
        }
        queryWrapper.eq(ApArticle::getIsDelete,false);
        queryWrapper.eq(ApArticle::getIsDown,false);
        //根据发布时间降序查询
        queryWrapper.orderByDesc(ApArticle::getPublishTime);
        //分页查询
        IPage<ApArticle> page = new Page<>(1,dto.getSize());
        IPage<ApArticle> page1 = this.page(page,queryWrapper);
        return ResponseResult.okResult(page1.getRecords());
    }
    @Override
    public ResponseResult loadArticleInfo(ArticleInfoDto dto) {
        //根据id查询文章
        ApArticle apArticle = this.getById(dto.getArticleId());
        if(apArticle == null|| apArticle.getIsDelete()||apArticle.getIsDown()){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //根据id查询文章内容
        LambdaQueryWrapper<ApArticleContent> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApArticleContent::getArticleId,dto.getArticleId());
        ApArticleContent apArticleContent = iApArticleContentService.getOne(queryWrapper);
        Map<String,Object> map = new HashMap<>();
        map.put("config",apArticle);
        map.put("content",apArticleContent);
        return ResponseResult.okResult(map);
    }

    @Override
    public void compute() {
        //获取今日时间和五天前的时间
        LambdaQueryWrapper<ApArticle> queryWrapper = Wrappers.lambdaQuery();
        //使用joda-time中的工具类,查询两百天之前的数据
        Date toDate = DateTime.now().minusDays(200).toDate();
        LambdaQueryWrapper<ApArticle> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(ApArticle::getIsDelete,false);
        queryWrapper1.eq(ApArticle::getIsDown,false);
        queryWrapper1.ge(ApArticle::getPublishTime,toDate);
        List<ApArticle> list = this.list(queryWrapper1);
        //先删除再放数据'
        Set<String> keys = redisTemplate.keys("hot_article_first_page_*");
        redisTemplate.delete(keys);

        List<ApArticle> list1 = this.list(queryWrapper);
        for (ApArticle apArticle : list1) {
            int score = computeScore(apArticle);
            ApArticle article = new ApArticle();
            article.setId(apArticle.getId());
            article.setTitle(apArticle.getTitle());
            article.setImages(apArticle.getImages());
            article.setAuthorId(apArticle.getAuthorId());
            article.setAuthorName(apArticle.getAuthorName());
            article.setLayout(apArticle.getLayout());
            article.setStaticUrl(apArticle.getStaticUrl());
            String jsonString = JSON.toJSONString(article);
            redisTemplate.boundZSetOps("hot_article_first_page_0").add(jsonString,score);
            redisTemplate.boundZSetOps("hot_article_first_page_"+apArticle.getChannelId()).add(jsonString,score);
        }
    }

    private int computeScore(ApArticle apArticle) {
        int score = 0;
        //阅读 + 1 点赞 + 3 评论 + 5 收藏 + 8
        if (apArticle.getViews()!=null){
            score+=apArticle.getViews()*1;
        }
        if (apArticle.getLikes()!=null){
            score +=apArticle.getLikes()*5;
        }
        if (apArticle.getComment()!=null){
            score += apArticle.getComment() *5;
        }
        if (apArticle.getCollection()!=null){
            score += apArticle.getCollection()*8;
        }
        return score;
    }
}
